using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using ODT.Common.Core;
using ODT.Common.ExtensionMethods;
using ODT.Common.Services;
using ODT.GlobalMessageProcessor;
using ODT.Intellisense.Core;
using ODT.PMACGlobal;
using PopupControl;

namespace IntellisenseControl
{
	public class Intellisense : UserControl
	{
		public delegate void OnIntellisenseSelect(string text);

		public delegate void UnProcessedKey(KeyEventArgs e);

		public delegate void LogIntellisense(string text);

		private const string PpmacDatabaseName = "ppmac";

		private readonly ILanguageTranslationService languageTranslationService;

		private readonly IDatabaseService databaseService;

		private readonly IIntellisenseProcessor processor;

		private MessageReceiverClass SinkDatabaseSync = new MessageReceiverClass(MessageReceiverClass.SyncType.GlobalDatabaseSync);

		private MessageReceiverClass SinkResetComplete = new MessageReceiverClass(MessageReceiverClass.SyncType.GlobalResetComplete);

		private MessageReceiverClass SinkRebootComplete = new MessageReceiverClass(MessageReceiverClass.SyncType.GlobalRebootComplete);

		private MessageReceiverClass SinkConnect = new MessageReceiverClass(MessageReceiverClass.SyncType.GlobalConnect);

		private MessageReceiverClass SinkDisconnect = new MessageReceiverClass(MessageReceiverClass.SyncType.GlobalDisconnect);

		private object databaseLock = new object();

		private static object intellisenseQueryLock = new object();

		private string inputText = string.Empty;

		private string previousInputText = string.Empty;

		private string database = "ppmac";

		private List<string> level0 = new List<string>();

		private ToolTip toolTip = new ToolTip();

		private bool firstAfterEvent = true;

		private string connectionString;

		private bool listTopReached;

		private IContainer components;

		private ListBox listBox1;

		public string InputText
		{
			get
			{
				return inputText;
			}
			set
			{
				previousInputText = inputText;
				inputText = value;
				lock (intellisenseQueryLock)
				{
					Processtext();
				}
			}
		}

		public int CurrentCursorPos { get; set; }

		public int ListBoxItemCount => listBox1.Items.Count;

		public string DataBase
		{
			get
			{
				return database;
			}
			set
			{
				lock (databaseLock)
				{
					database = value.Replace('.', '_');
					if (database.IsNoDevice())
					{
						database = "ppmac";
					}
					if (!database.ToLower().Contains("ppmac"))
					{
						database = "ppmac" + database;
					}
					database = database.Replace('.', '_');
					connectionString = databaseService.GetConnectionString(database);
					level0.Clear();
					level0 = PPIntellisense.CreateLevel0LanguageList(connectionString);
					List<string> collection = PPIntellisense.CreateUserVariableSpecificList(connectionString);
					level0.AddRange(collection);
					listBox1.Items.Clear();
					listBox1.BeginUpdate();
					try
					{
						listBox1.Items.AddRange(level0.ToArray());
					}
					catch (OutOfMemoryException)
					{
					}
					listBox1.EndUpdate();

					processor.OnConnected(value);
				}
			}
		}

		public string TypedChar { get; set; }

		public event OnIntellisenseSelect SelectedText;

		public event UnProcessedKey SendKeyUp;

		public event LogIntellisense LogIntellisenseMessage;

		public Intellisense(ILanguageTranslationService languageTranslationService)
		{
			this.languageTranslationService = languageTranslationService;
			databaseService = ServiceManager.GetService<IDatabaseService>();
			processor = ServiceManager.GetService<IIntellisenseProcessor>();
			
			InitializeComponent();
			SinkDatabaseSync.PPMACGlobalDatabaseSyncEvent += SinkDatabaseSync_PPMACGlobalDatabaseSyncEvent;
			SinkResetComplete.PPMACGlobalResetCompleteEvent += SinkResetComplete_PPMACGlobalResetCompleteEvent;
			SinkRebootComplete.PPMACGlobalRebootCompleteEvent += SinkRebootComplete_PPMACGlobalRebootCompleteEvent;
			SinkConnect.PPMACGlobalConnectEvent += SinkIpAdrChange_PPMACGlobalIPAddressChangeEvent;
			SinkDisconnect.PPMACGlobalDisconnectEvent += SinkDisconnect_PPMACGlobalDisconnectEvent;
			toolTip.UseAnimation = true;
			toolTip.UseFading = true;
		}

		public bool SetFocus(KeyEventArgs _key)
		{
			try
			{
				if (listBox1.Items.Count > 0 && listBox1.Visible)
				{
					if (listBox1.SelectedIndex == 0 && _key.KeyCode == Keys.Up)
					{
						listBox1.SelectedIndex = 0;
						listTopReached = true;
						return true;
					}
					if (listBox1.SelectedIndex >= 0)
					{
						listBox1_SelectedIndexChanged(null, null);
						listTopReached = false;
						listBox1.Focus();
						return true;
					}
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		public string GetSelectedText()
		{
			try
			{
				return (string)listBox1.SelectedItem;
			}
			catch
			{
				return string.Empty;
			}
		}

		public void ClearList()
		{
			listBox1.Items.Clear();
		}

		public void listBox1_KeyUp(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Tab || e.KeyCode == Keys.Space)
			{
				try
				{
					string value = (string)listBox1.SelectedItem;
					if (string.IsNullOrEmpty(value))
					{
						return;
					}
					if (this.SelectedText != null)
					{
						this.SelectedText(value);
					}
				}
				catch
				{
				}
			}
			if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down)
			{
				if (SetFocus(e))
				{
					if (listTopReached)
					{
						listTopReached = false;
						if (this.SendKeyUp != null)
						{
							this.SendKeyUp(e);
						}
					}
					else
					{
						e.Handled = true;
					}
				}
				else
				{
					e.Handled = false;
				}
			}
			if ((e.KeyCode == Keys.Escape || e.KeyCode == Keys.Back) && this.SendKeyUp != null)
			{
				this.SendKeyUp(e);
			}
		}

		protected override void WndProc(ref Message m)
		{
			if (!(base.Parent is Popup) || !(base.Parent as Popup).ProcessResizing(ref m))
			{
				base.WndProc(ref m);
			}
		}

		private void Processtext()
		{
			if (firstAfterEvent)
			{
				listBox1.Items.Clear();
				firstAfterEvent = false;
			}
			List<string> list = new List<string>();
			try
			{
				if (!databaseService.IsDatabaseRunning())
				{
					return;
				}
			}
			catch { }

			try
			{
				if (string.IsNullOrEmpty(inputText))
				{
					return;
				}
				if (inputText.Contains(".") && TypedChar.Equals("."))
				{
					//processor.FillSuggestions(inputText, list);
					//string s = processor.PickASuggestion(inputText, list);
					//listBox1.Items.Clear();
					//listBox1.Items.AddRange(list.ToArray());
					//int num = listBox1.ClientSize.Height / listBox1.ItemHeight;
					//int num2 = listBox1.FindString(s, -1);
					//if (num2 >= 0)
					//{
					//	listBox1.SelectedIndex = num2;
					//	if (listBox1.Items.Count > num)
					//	{
					//		listBox1.TopIndex = listBox1.SelectedIndex - num / 2;
					//	}
					//	else
					//	{
					//		listBox1.TopIndex = listBox1.SelectedIndex;
					//	}
					//}
					//else
					//{
					//	listBox1.SelectedIndex = -1;
					//}
					return;
				}
				string lastWord = getLastWord(inputText, CurrentCursorPos);
				string[] array = inputText.Split(new char[6] { ' ', '=', '+', '-', '*', '/' }, StringSplitOptions.RemoveEmptyEntries);
				int num3 = listBox1.ClientSize.Height / listBox1.ItemHeight;
				if (!array[array.Length - 1].Contains(".") && listBox1.Items.Count <= 0)
				{
					list = PPIntellisense.CreateLevel0LanguageList(connectionString);
					list.AddRange(PPIntellisense.CreateUserVariableSpecificList(connectionString));
					listBox1.Items.Clear();
					listBox1.BeginUpdate();
					listBox1.Items.AddRange(list.ToArray());
					listBox1.EndUpdate();
				}
				if (!string.IsNullOrEmpty(lastWord))
				{
					int num4 = listBox1.FindString(lastWord, -1);
					if (num4 >= 0)
					{
						listBox1.SelectedIndex = num4;
						if (listBox1.Items.Count > num3)
						{
							listBox1.TopIndex = listBox1.SelectedIndex - num3 / 2;
						}
						else
						{
							listBox1.TopIndex = listBox1.SelectedIndex;
						}
					}
					else
					{
						listBox1.SelectedIndex = -1;
					}
					return;
				}
				int num5 = listBox1.FindString(inputText, -1);
				if (num5 >= 0)
				{
					listBox1.SelectedIndex = num5;
					if (listBox1.Items.Count > num3)
					{
						listBox1.TopIndex = listBox1.SelectedIndex - num3 / 2;
					}
					else
					{
						listBox1.TopIndex = listBox1.SelectedIndex;
					}
				}
				else
				{
					listBox1.SelectedIndex = -1;
				}
			}
			catch (Exception ex)
			{
				if (this.LogIntellisenseMessage != null)
				{
					this.LogIntellisenseMessage(ex.Message);
				}
			}
		}

		private string RemoveNumbersFromBracket(string InputString, ref int _num, char _bracketCharopen, char _bracketCharClose)
		{
			string text = InputString;
			if (text.Contains(_bracketCharopen.ToString()))
			{
				int num = text.IndexOf(_bracketCharopen);
				int num2 = text.IndexOf(_bracketCharClose);
				if (num2 - num > 1)
				{
					string text2 = text.Substring(num + 1, num2 - num - 1);
					text2 = text2.Trim();
					try
					{
						_num = int.Parse(text2);
					}
					catch (FormatException)
					{
					}
					text = text.Remove(num + 1, num2 - num - 1);
					text = text.Trim('.');
				}
			}
			return text;
		}

		private string getLastWord(string text, int curpos)
		{
			string text2 = string.Empty;
			int num = curpos;
			if (num >= 1)
			{
				string empty = string.Empty;
				char c = '\0';
				while (num > 0 && text.Length > 0)
				{
					num--;
					try
					{
						empty = ((text.Length != num) ? text.Substring(num, 1) : string.Empty);
					}
					catch (ArgumentOutOfRangeException)
					{
						empty = string.Empty;
					}
					string text3 = text.ToLower();
					try
					{
						if (string.IsNullOrEmpty(empty))
						{
							return text2;
						}
						c = empty[0];
					}
					catch
					{
						return text2;
					}
					if ((c.CompareTo('.') == 0 || c.CompareTo('=') == 0 || c.CompareTo('+') == 0 || c.CompareTo('-') == 0 || c.CompareTo('*') == 0 || c.CompareTo('/') == 0 || c.CompareTo(' ') == 0) && text3[0].CompareTo('j') != 0)
					{
						break;
					}
					text2 += c;
				}
				char[] array = text2.ToCharArray();
				Array.Reverse(array);
				text2 = new string(array);
			}
			return text2.Trim();
		}

		private string getLastWordForOEMPeriod(string text, int curpos)
		{
			string text2 = string.Empty;
			int num = curpos;
			if (num >= 1)
			{
				string empty = string.Empty;
				char c = '\0';
				while (num > 0 && text.Length > 0)
				{
					num--;
					try
					{
						empty = text.Substring(num, 1);
					}
					catch (ArgumentOutOfRangeException)
					{
						empty = string.Empty;
					}
					c = empty[0];
					if (c.CompareTo('=') == 0 || c.CompareTo('+') == 0 || c.CompareTo('-') == 0 || c.CompareTo('*') == 0 || c.CompareTo('/') == 0 || c.CompareTo(' ') == 0)
					{
						break;
					}
					text2 += c;
				}
				char[] array = text2.ToCharArray();
				Array.Reverse(array);
				text2 = new string(array);
			}
			return text2.Trim();
		}

		private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
		{
			string text = (string)listBox1.SelectedItem;
			if (!string.IsNullOrEmpty(text))
			{
				//string helpText = processor.GetHelpText(text);
				//if (!string.IsNullOrEmpty(helpText))
				//{
				//	int num = listBox1.Size.Width;
				//	Rectangle itemRectangle = listBox1.GetItemRectangle(listBox1.SelectedIndex);
				//	toolTip.Show(helpText, listBox1, num, itemRectangle.Y, 3000);
				//}
			}
		}

		private void listBox1_DoubleClick(object sender, EventArgs e)
		{
			if (this.SelectedText != null)
			{
				this.SelectedText((string)listBox1.SelectedItem);
			}
		}

		private void SinkIpAdrChange_PPMACGlobalIPAddressChangeEvent(object sender, MessageReceiverClass.IPChangeMessageReceiverEvnetArgs e)
		{
			if (e.handle.ToInt32() == IDEGlobals.VSHandle.ToInt32())
			{
				lock (intellisenseQueryLock)
				{
					DataBase = e.ipAddress;
					firstAfterEvent = true;
				}
			}
		}

		private void SinkDisconnect_PPMACGlobalDisconnectEvent(object sender, MessageReceiverClass.IPChangeMessageReceiverEvnetArgs e)
		{
			if (e.handle.ToInt32() == IDEGlobals.VSHandle.ToInt32())
			{
				lock (intellisenseQueryLock)
				{
					DataBase = IPAddress.NoDevice.ToString();
					firstAfterEvent = true;
				}
			}
		}

		private void SinkRebootComplete_PPMACGlobalRebootCompleteEvent(object sender, MessageReceiverClass.IPChangeMessageReceiverEvnetArgs e)
		{
			if (DataBase == "ppmac" + e.ipAddress.Replace(".", "_"))
			{
				lock (intellisenseQueryLock)
				{
					DataBase = e.ipAddress;
					firstAfterEvent = true;
				}
			}
		}

		private void SinkResetComplete_PPMACGlobalResetCompleteEvent(object sender, MessageReceiverClass.IPChangeMessageReceiverEvnetArgs e)
		{
			if (DataBase == "ppmac" + e.ipAddress.Replace(".", "_"))
			{
				lock (intellisenseQueryLock)
				{
					DataBase = e.ipAddress;
					firstAfterEvent = true;
				}
			}
		}

		private void SinkDatabaseSync_PPMACGlobalDatabaseSyncEvent(object sender, MessageReceiverClass.DataSyncMessageReceiverEvnetArgs e)
		{
			if (!(DataBase == "ppmac" + e.ipAddress.Replace(".", "_")))
			{
				return;
			}
			lock (intellisenseQueryLock)
			{
				if (!string.IsNullOrEmpty(e.ipAddress) && !e.ipAddress.IsNoDevice())
				{
					DataBase = e.ipAddress;
					firstAfterEvent = true;
				}
				if (this.LogIntellisenseMessage != null)
				{
					this.LogIntellisenseMessage(languageTranslationService.Translate("IntellisenseControl.DataBaseSyncEventReceived"));
				}
			}
		}

		private void StopMonitoring()
		{
			SinkDatabaseSync.PPMACGlobalDatabaseSyncEvent -= SinkDatabaseSync_PPMACGlobalDatabaseSyncEvent;
			SinkResetComplete.PPMACGlobalResetCompleteEvent -= SinkResetComplete_PPMACGlobalResetCompleteEvent;
			SinkRebootComplete.PPMACGlobalRebootCompleteEvent -= SinkRebootComplete_PPMACGlobalRebootCompleteEvent;
			SinkConnect.PPMACGlobalConnectEvent -= SinkIpAdrChange_PPMACGlobalIPAddressChangeEvent;
			SinkDisconnect.PPMACGlobalDisconnectEvent -= SinkDisconnect_PPMACGlobalDisconnectEvent;
			SinkDatabaseSync.StopMonitoring();
			SinkResetComplete.StopMonitoring();
			SinkRebootComplete.StopMonitoring();
			SinkConnect.StopMonitoring();
			SinkDisconnect.StopMonitoring();
		}

		protected override void Dispose(bool disposing)
		{
			try
			{
				if (disposing)
				{
					StopMonitoring();
					if (components != null)
					{
						components.Dispose();
					}
				}
				base.Dispose(disposing);
			}
			catch
			{
			}
		}

		private void InitializeComponent()
		{
			this.listBox1 = new System.Windows.Forms.ListBox();
			base.SuspendLayout();
			this.listBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;
			this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill;
			this.listBox1.FormattingEnabled = true;
			this.listBox1.ItemHeight = 14;
			this.listBox1.Location = new System.Drawing.Point(0, 0);
			this.listBox1.Name = "listBox1";
			this.listBox1.ScrollAlwaysVisible = true;
			this.listBox1.Size = new System.Drawing.Size(145, 126);
			this.listBox1.Sorted = true;
			this.listBox1.TabIndex = 0;
			this.listBox1.SelectedIndexChanged += new System.EventHandler(listBox1_SelectedIndexChanged);
			this.listBox1.DoubleClick += new System.EventHandler(listBox1_DoubleClick);
			this.listBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(listBox1_KeyUp);
			base.AutoScaleDimensions = new System.Drawing.SizeF(6f, 14f);
			base.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
			base.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
			base.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
			base.Controls.Add(this.listBox1);
			this.DoubleBuffered = true;
			this.Font = new System.Drawing.Font("Arial", 8.25f, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0);
			this.MinimumSize = new System.Drawing.Size(100, 54);
			base.Name = "Intellisense";
			base.Padding = new System.Windows.Forms.Padding(0, 0, 0, 5);
			base.Size = new System.Drawing.Size(145, 140);
			base.ResumeLayout(false);
		}
	}
}
